home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-03-07 | 6.8 KB | 298 lines | [TEXT/R*ch] |
- //
- // from 'ADB Key Spy' • Pete Gontier • gurgle@apple.com
- // Macintosh Developer Technical Support
- // © 1995,1996 Apple Computer, Inc.
- //
- // Changes:
- //
- // when who what
- // --------------------------------------------------------------
- // 11/12/96 Quinn modified to use TradDriverLoaderLib
- // 01/11/96 PG copied from another project,
- // merged with various parts of old
- // ADB Key Spy
- //
-
- #ifndef __DEVICES__
- # include <Devices.h>
- #endif
-
- #ifndef __RESOURCES__
- # include <Resources.h>
- #endif
-
- #ifndef __MEMORY__
- # include <Memory.h>
- #endif
-
- #ifndef __LOWMEM__
- # include <LowMem.h>
- #endif
-
- #ifndef __A4STUFF__
- # include <A4Stuff.h>
- #endif
-
- #include "ADBKS Common.h"
- #include "ADBKS csCodes.h"
-
- #include "TradDriverLoaderLib.h"
-
- //
- // vKeyboardServiceRoutineAsm
- //
- // This is a declaration for a function which is in fact
- // never called from C but only by ADB and consists of 68K
- // assembly. However, I pass the thing around enough that
- // it was convenient to define a type for it.
- //
-
- typedef asm void (vKeyboardServiceRoutineAsm) (void);
-
- //
- // dCtlFlags
- //
- // These are the device control entry flags for the driver.
- // Compiler doesn't allow me to specify them with quite enough
- // flexibility (i.e. none), and I don't want to put a manual
- // resource edit into the build process, so I have code do it.
- //
-
- const short dCtlFlags = dRAMBasedMask | dCtlEnableMask | dStatEnableMask;
-
- enum
- {
- //
- // Some miscellaneous quantities needed for installing a driver
- // into the unit table which for whatever reason do not
- // appear in <Devices.h>.
- //
-
- kMaxUTEntries = 128, // maximum size of unit table
- kMinUnitNum = 48 // lowest unit number we can use
- };
-
- static pascal OSErr GetKMAP (tKeyboardInfo *kbInfo, char devType)
- {
- //
- // GetKMAP
- //
- // The 'KMAP' resources map raw key codes to virtual key codes.
- // To make it possible for the service routine to easily perform
- // this mapping, we toss a handle to the appropriate 'KMAP'
- // resource into each keyboard info record.
- //
- // The resource is marked locked, so it's interrupt-safe.
- // The resource is marked system-heap, which is what we want
- // because we are an INIT and our heap will disappear soon.
- //
- // One is not supposed to release resources which potentially come from
- // the System file because they might be shared. Thus, we get our resource
- // and keep it ("leak" it). If you have 'KMAP' resources in some other file
- // for some reason, then you might want to call HomeResFile here to help
- // you decide whether to release the resource.
- //
-
- OSErr err = noErr;
-
- const ResType kmapResType = 'KMAP';
-
- tKeyMapResourceH kmapH = (tKeyMapResourceH) GetResource (kmapResType, devType);
- err = ResError ( );
- if (err == resNotFound || !kmapH)
- {
- kmapH = (tKeyMapResourceH) GetResource (kmapResType, 0);
- err = ResError ( );
- if (err == resNotFound)
- {
- err = noErr;
- kmapH = nil; // just to be sure
- }
- }
-
- kbInfo->keyMapResH = kmapH;
-
- return err;
- }
-
- static pascal OSErr AcquireKeyboards
- (vKeyboardServiceRoutineAsm *serviceRoutine, tKeyboardInfoP *keyboardInfoList)
- {
- //
- // Walks the ADB device list and patches the service routine
- // of each keyboard so that an extra (internal) key map is maintained.
- // A block of memory is allocated via NewPtr for each keyboard.
- // Blocks are strung together into a list and returned.
- //
-
- OSErr err = noErr;
-
- ADBSetInfoBlock siBlock;
- ADBDataBlock adbInfo;
-
- short adbCount = CountADBs ( );
-
- *keyboardInfoList = nil;
-
- while (adbCount)
- {
- ADBAddress adbAddress = GetIndADB (&adbInfo, adbCount);
-
- if (adbAddress < 0)
- {
- DebugStr ("\p adbAddress < 0 ?");
- err = paramErr;
- break;
- }
-
- if (adbInfo.origADBAddr == 2) // 2 == keyboard
- {
- //
- // allocate a new record to track old service proc addresses
- //
-
- tKeyboardInfo *newKeyboardInfo =
- (tKeyboardInfo *) NewPtrSysClear (sizeof (tKeyboardInfo));
- err = MemError ( );
- if (err) break;
-
- //
- // fill in the new record and get ready to insert it into our list
- //
-
- err = GetKMAP (newKeyboardInfo, adbInfo.devType);
- if (err)
- {
- DisposePtr ((Ptr) newKeyboardInfo);
- break;
- }
-
- newKeyboardInfo->dbDataAreaAddr = adbInfo.dbDataAreaAddr;
- newKeyboardInfo->dbServiceRtPtr = adbInfo.dbServiceRtPtr;
- newKeyboardInfo->next = *keyboardInfoList;
-
- //
- // replace the device's service routine and data pointer
- //
-
- siBlock.siService = (ADBServiceRoutineUPP) serviceRoutine;
- siBlock.siDataAreaAddr = (Ptr) newKeyboardInfo;
-
- err = SetADBInfo (&siBlock, adbAddress);
- if (err)
- {
- DisposePtr ((Ptr) newKeyboardInfo);
- break;
- }
-
- //
- // insert the new record into our list
- //
-
- *keyboardInfoList = newKeyboardInfo;
- }
-
- --adbCount;
- }
-
- return err;
- }
-
- static pascal OSErr GetServiceRoutine (vKeyboardServiceRoutineAsm **ksra)
- {
- //
- // Loads and detaches the ADB service routine code resource.
- // Produces the ADB service routine address.
- // A copy of the resource stays loaded; call DisposeHandle to free it.
- //
-
- OSErr err = noErr;
-
- //
- // Assume AKSR 128 is system heap, locked, pre-load.
- //
-
- Handle serviceRoutineH = Get1Resource ('AKSR',128);
-
- *ksra = nil;
-
- if (!(err = ResError ( )))
- {
- DetachResource (serviceRoutineH);
- if (!(err = ResError ( )))
- *ksra = (vKeyboardServiceRoutineAsm *) *serviceRoutineH;
- else
- ReleaseResource (serviceRoutineH);
- }
-
- return err;
- }
-
- static pascal OSErr AcquireKeyboardsAndLinkToDriver (ConstStr255Param myDriverName)
- {
- //
- // Gets the address of the service routine.
- // Calls AquireKeyboards to patch all keyboard ADB service routines
- // and obtain a list of patched keyboard ADB info records.
- // Tells driver about this list.
- //
-
- short drvrRefNum;
-
- OSErr err = OpenDriver (myDriverName, &drvrRefNum);
-
- if (!err)
- {
- OSErr err2 = noErr;
- vKeyboardServiceRoutineAsm *ksra = nil;
- if (!(err = GetServiceRoutine (&ksra)))
- {
- tKeyboardInfo *keyboardInfoList = nil;
- err = AcquireKeyboards (ksra, &keyboardInfoList);
-
- //
- // Even if there was an error, there might be a partial list,
- // so we attempt to install it.
- //
-
- if (keyboardInfoList)
- {
- err2 = Control (drvrRefNum,kControlCode_SetKeyboardInfoList,&keyboardInfoList);
- if (!err) err = err2;
- }
- }
-
- //
- // Close the driver no matter what once it's been opened.
- // However, don't report errors on close unless nothing else
- // has gone wrong first.
- //
-
- err2 = CloseDriver (drvrRefNum);
- if (!err) err = err2;
- }
-
- return err;
- }
-
- void main (void)
- {
- long oldA4 = SetCurrentA4 ( );
- unsigned char *myDriverName = "\p.adb_key_spy";
-
- // Quinn 11/12/96
- DriverRefNum drvrRefNum;
- OSErr err;
- err = TradInstallDriverFromResource(0, myDriverName,
- 48,
- TradHighestUnitNumber() + 1,
- &drvrRefNum);
- if (err == noErr || err == dupFNErr) {
- err = TradOpenInstalledDriver(drvrRefNum, fsRdWrPerm);
- }
-
- if (!err) err = AcquireKeyboardsAndLinkToDriver (myDriverName);
- if (err) SysBeep (10);
- SetA4 (oldA4);
- }
-